package monitor

import (
	"gitee.com/amoyx/cloud-provider/pkg/cloud/tencent/models"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	mo "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/monitor/v20180724"
	"strings"
)

type GrafanaGreeter interface {
	Grafana(region string) GrafanaInterface
}

type GrafanaInterface interface {
	Get(id string) (result models.GrafanaResponse, err error)
	ListByName(name string) (list []models.GrafanaResponse, err error)
	ListByStatus(status int64) (list []models.GrafanaResponse, err error)
	ListAll() (list []models.GrafanaResponse, err error)
	CreateInstance(args models.GrafanaRequest) (result models.CreateResponseParams, err error)
	DestroyInstance(id string) (err error)
	DeleteInstance(id string) (err error)
	ResumeInstance(id string) (err error)
	WhiteList(id string) (list []string, err error)
	EnableWanAddr(id string) (err error)
	DisableWanAddr(id string) (err error)
	UpdateWhiteList(id string, ipList []string) (err error)
}

type grafana struct {
	m      *Monitor
	region string
	client *mo.Client
}

func newGrafana(monitor *Monitor, region string) GrafanaInterface {
	v := &grafana{
		m:      monitor,
		region: region,
	}
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = string(MonitorEndPoint)
	client, _ := mo.NewClient(v.m.Credential(), v.region, cpf)
	v.client = client
	return v
}

// CreateInstance 创建grafana实例
func (g *grafana) CreateInstance(args models.GrafanaRequest) (result models.CreateResponseParams, err error) {
	request := mo.NewCreateGrafanaInstanceRequest()
	request.InstanceName = common.StringPtr(args.InstanceName)
	request.VpcId = common.StringPtr(args.VpcId)
	request.SubnetIds = common.StringPtrs([]string{args.SubnetId})
	request.GrafanaInitPassword = common.StringPtr(args.Password)
	request.EnableInternet = common.BoolPtr(args.EnableInternet)
	response, err := g.client.CreateGrafanaInstance(request)
	if err != nil {
		return
	}
	res := response.Response
	result.RequestId = *res.RequestId
	result.InstanceSet = append(result.InstanceSet, *res.InstanceId)
	return
}

// DeleteInstance 删除/释放实例, 做此动作之前，需要先销毁实例
func (g *grafana) DeleteInstance(id string) (err error) {
	request := mo.NewCleanGrafanaInstanceRequest()
	request.InstanceId = common.StringPtr(id)
	_, err = g.client.CleanGrafanaInstance(request)
	return
}

// DestroyInstance 销毁/退还 实例
func (g *grafana) DestroyInstance(id string) (err error) {
	request := mo.NewDeleteGrafanaInstanceRequest()
	request.InstanceIDs = common.StringPtrs([]string{id})
	_, err = g.client.DeleteGrafanaInstance(request)
	return
}

// ResumeInstance 恢复已删除实例
func (g *grafana) ResumeInstance(id string) (err error) {
	request := mo.NewResumeGrafanaInstanceRequest()
	request.InstanceId = common.StringPtr(id)
	_, err = g.client.ResumeGrafanaInstance(request)
	return
}

// WhiteList 获取grafana实例白名单列表
func (g *grafana) WhiteList(id string) (list []string, err error) {
	request := mo.NewDescribeGrafanaWhiteListRequest()
	request.InstanceId = common.StringPtr(id)
	response, err := g.client.DescribeGrafanaWhiteList(request)
	if err != nil {
		return
	}
	for _, ip := range response.Response.WhiteList {
		list = append(list, *ip)
	}
	return
}

// EnableWanAddr 开启公网访问
func (g *grafana) EnableWanAddr(id string) (err error) {
	request := mo.NewEnableGrafanaInternetRequest()
	request.InstanceID = common.StringPtr(id)
	request.EnableInternet = common.BoolPtr(true)
	_, err = g.client.EnableGrafanaInternet(request)
	return
}

// DisableWanAddr 关闭公网访问
func (g *grafana) DisableWanAddr(id string) (err error) {
	request := mo.NewEnableGrafanaInternetRequest()
	request.InstanceID = common.StringPtr(id)
	request.EnableInternet = common.BoolPtr(false)
	_, err = g.client.EnableGrafanaInternet(request)
	return
}

func (g *grafana) UpdateWhiteList(id string, ipList []string) (err error) {
	request := mo.NewUpdateGrafanaWhiteListRequest()
	request.InstanceId = common.StringPtr(id)
	request.Whitelist = common.StringPtrs(ipList)
	_, err = g.client.UpdateGrafanaWhiteList(request)
	return
}

func (g *grafana) Get(id string) (result models.GrafanaResponse, err error) {
	list, err := g.query(id, "", 0)
	if len(list) > 0 {
		result = list[0]
	}
	return
}
func (g *grafana) ListByName(name string) (list []models.GrafanaResponse, err error) {
	return g.query("", name, 0)
}

func (g *grafana) ListByStatus(status int64) (list []models.GrafanaResponse, err error) {
	return g.query("", "", status)
}

func (g *grafana) ListAll() (list []models.GrafanaResponse, err error) {
	return g.query("", "", 0)
}

func (g *grafana) query(id string, name string, status int64) (list []models.GrafanaResponse, err error) {
	request := mo.NewDescribeGrafanaInstancesRequest()
	if strings.TrimSpace(id) != "" {
		request.InstanceIds = common.StringPtrs([]string{id})
	}
	if strings.TrimSpace(name) != "" {
		request.InstanceName = common.StringPtr(name)
	}
	if status > 0 {
		request.InstanceStatus = common.Int64Ptrs([]int64{status})
	}
	request.Offset = common.Int64Ptr(0)
	request.Limit = common.Int64Ptr(1000)
	response, err := g.client.DescribeGrafanaInstances(request)
	if err != nil {
		return
	}
	for _, row := range response.Response.Instances {
		var sids []string
		for _, sid := range row.SubnetIds {
			sids = append(sids, *sid)
		}
		list = append(list, models.GrafanaResponse{
			InstanceName:       *row.InstanceName,
			InstanceId:         *row.InstanceId,
			Region:             *row.Region,
			VpcId:              *row.VpcId,
			SubnetIds:          sids,
			InternetUrl:        *row.InternetUrl,
			InternalUrl:        *row.InternalUrl,
			CreatedAt:          *row.CreatedAt,
			InstanceStatus:     *row.InstanceStatus,
			Zone:               *row.Zone,
			InstanceChargeType: *row.InstanceChargeType,
			VpcName:            *row.VpcName,
			SubnetName:         *row.SubnetName,
			RegionId:           *row.RegionId,
			RootUrl:            *row.RootUrl,
			EnableSSO:          *row.EnableSSO,
			Version:            *row.Version,
			EnableSSOCamCheck:  *row.EnableSSOCamCheck,
		})
	}
	return
}
